﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Xceed.Document.NET;
using Xceed.Words.NET;

namespace FilterIllegalCharacter.Core
{
    public static class OpenXmlExtension
    {
        /// <summary>
        /// 高亮word文档里的文本
        /// </summary>
        /// <param name="doc">word文档</param>
        /// <param name="rnodes">需要高亮的文本参数</param>
        /// <param name="color">高亮的颜色</param>
        /// <returns></returns>
        public static void HighlightText(this DocX doc, List<RNode> rnodes, Highlight? color, Action<object?, double>? progressBarEvent = null)
        {
            if (color == null)
            {
                // 给一个默认值黄色
                color = Highlight.yellow;
            }
            // 定位到段落的位置
            var paragraphs = doc.Paragraphs;
            int textLength = 0;
            //progressBarEvent?.Invoke(null, 0d);
            for (int i = 0; i < paragraphs.Count; i++)
            {
                var rnodes1 = rnodes.Where(x => x.start >= textLength && x.start < textLength + paragraphs[i].Text.Length).ToList();
                if (rnodes1.Count > 0)
                {
                    Paragraph para = paragraphs[i];
                    foreach (var rnode in rnodes1)
                    {
                        // 根据文本全文索引计算文本在当前段落的索引
                        int index = rnode.start - textLength;
                        // 如果索引加长度没有超出当前段落则直接删除文本然后插入高亮的文本
                        if (index + rnode.len <= para.Text.Length)
                        {
                            string text = para.Text.Substring(index, rnode.len);
                            // 此处要先插入后删除，避免段落只有关键字的情况下删除段落会消失
                            // 在段落中插入高亮文本
                            para.InsertText(index, text, false, new Formatting() { Highlight = color });
                            // 在段落中删除文本
                            para.RemoveText(index + rnode.len, rnode.len);
                        }
                        else if (paragraphs.Count > i + 1)
                        {
                            //超出了当前段落则表示要高亮当前段落末尾和下一段落开头
                            Paragraph nextPara = paragraphs[i + 1];
                            int overlength = (index + rnode.len) - para.Text.Length;
                            string text = para.Text.Substring(index);
                            // 在段落中插入高亮文本
                            para.InsertText(index, text, false, new Formatting() { Highlight = color });
                            // 在段落中删除文本
                            para.RemoveText(index + rnode.len - overlength, rnode.len - overlength);
                            string nextText = nextPara.Text.Substring(0, overlength);
                            // 先插入后删除
                            nextPara.InsertText(0, nextText, false, new Formatting() { Highlight = color });
                            // 在段落中删除文本且插入高亮文本
                            nextPara.RemoveText(overlength, overlength);
                        }
                        else
                        {
                            throw new Exception($"{rnode.text}：当前文本索引和长度超出范围");
                        }
                    }
                }
                textLength += paragraphs[i].Text.Length;
                double progress = i * 100d / paragraphs.Count + 100;
                progressBarEvent?.Invoke(null, progress);
            }
        }
        /// <summary>
        /// 判断是否word文档
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static bool IsWordDocument(this string filePath)
        {
            FileInfo fileInfo = new FileInfo(filePath);
            if (fileInfo.Extension == ".doc" || fileInfo.Extension == ".docx")
            {
                return true;
            }
            else
            {
                using (FileStream fileStream = fileInfo.OpenRead())
                {
                    byte[] buffer = new byte[2];
                    int bytesRead = fileStream.Read(buffer, 0, 2);
                    if (bytesRead == 2)
                    {
                        ushort word = BitConverter.ToUInt16(buffer, 0);
                        // Check if the file starts with the Microsoft Word document signature
                        if (word == 0x205E || word == 0x2046 || word == 0x5C7E)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
    }
}